#include <iostream>
#include <unistd.h>
#include <pthread.h>


#if 0
/*
 * 线程的ID
 */
    pthread_create创建一个线程，产生一个线程ID存放在第一个参数之中，该线程ID与内核中的LWP并不是一回事。

    pthread_create函数第一个参数指向一块虚拟内存单元，该内存单元的地址就是新创建线程ID，
    这个ID是线程库的范畴，而内核中LWP是进程调度的范畴，轻量级进程是OS调度的最小单位，
    需要一个数值来表示该唯一线程。

    Linux并不提供真正的线程，只提供了LWP，但是程序员用户不管LWP，只要线程。
    所以OS在OS与应用程序之间设计了一个原生线程库，pthread库，系统保存LWP，
    原生线程库可能存在多个线程，别人可以同时在用。OS只需要对内核执行流LWP进行管理，
    而提供用户使用的线程接口等其他数据则需要线程库自己来管理。

    所以线程库需要对线程管理“先描述，在组织”。

    线程库实际上就是一个动态库：
#endif

#if 0
/*
 * 进程运行时动态库加载到内存，然后通过页表映射到进程地址空间的共享区，
 * 这时候进程的所有线程都是能看到这个动态库的：libpthread.a libthread.so
 */

每个线程都有自己独立的栈：
主线程采用的栈是进程地址空间中原生的栈，其他线程采用的是共享区中的栈，
每个线程都有自己的struct pthread,包含了对应线程的属性，
每个线程也有自己的线程局部存储（添加__thread可以将一个内置类型设置为线程局部存储），
包含对应的线程被切换时的上下文。

每一个新的线程在共享区都有一块区域对其描述，
所以我们要找到一个用户级线程只需要找到该线程内存块的起始地址就可以获取到该线程的信息了.

|--------------------
| 动态库
    ---------------
    |struct pthread          --> pthread_t tid1
    ---------------
    |线程局部存储
    ---------------
    |线程栈
    ---------------
    ---------------
    |struct pthread          --> pthread_t tid2
    ---------------
    |线程局部存储
    ---------------
    |线程栈
    ---------------
|--------------------


线程函数起始是在库内部对线程属性进行操作，最后将要执行的代码交给对应的内核级LWP去执行。
所以线程数据的管理本质在共享区。

线程ID本质就是进程地址空间共享区上的一个虚拟地址：

https://cloud.tencent.com/developer/article/2341682?areaId=106001

#endif

void* start_routine(void *args)
{
    while (true) {
        printf("new thread tid:%p\n", pthread_self());
        sleep(2);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, start_routine, nullptr);

    while (true) {
        printf("main thread tid:%p\n", pthread_self());
        sleep(1);
    }

    return 0;
}

